#include "stdafx.h"
#include "Isoform.h"

CTIsoform::CTIsoform()
{
}

CTIsoform::~CTIsoform()
{
}

int CTIsoform::printIsoform(ostream& out)
{
    unsigned int i;
    for (i = 0; i < this->exons.size(); i++) {
        out << "\t" << this->exons.at(i).first <<','<< this->exons.at(i).second;
    }
    out << endl;
    return(i);
}

// for each exon first < second however, in forw
int CTIsoform::addExon(pair <int, int> Exon, bool forward)
{
    if (exons.empty()) {
        this->forward = forward;
    }
    if (this->forward != forward) {
        return(-1); // adding exon with wrong direction
    }

    bool validExon = false;

    if (Exon.first <= Exon.second) {
        if (forward) {
            if (this->exons.empty() ||
                    (Exon.first > this->exons.back().second)) {
                validExon = true;
            }
        } else {
            if (this->exons.empty() ||
                    (Exon.second < this->exons.back().first)) {
                validExon = true;
            }
        }
    }
    if (validExon) {
        this->exons.push_back(Exon);
        return(this->exons.size());
    }
    return(this->exons.size());
}

int CTIsoform::deleteExon()
{
    if (this->exons.size() > 0) {
        this->exons.pop_back();
    }
    return(this->exons.size());
}

CIsoformInfo::CIsoformInfo(string isoformId)
{
    this->initialization();
    this->isoformId = isoformId;
}

CIsoformInfo::CIsoformInfo(CTIsoform& isoform)
{
    this->initialization();
    this->exons = isoform.exons;
    this->forward = isoform.forward;
}

CIsoformInfo::~CIsoformInfo(void)
{
}

int CIsoformInfo::initialization(void)
{
    this->aaSize = 0;
    this->ntSize = 0;
    this->CDSscore = 0;
    this->isoformId = string("");
    this->geneName = string("");
    this->frame = pair<int,int>(0,0);
    this->seq = string("");
    this->codingSeq = string("");
    return(0);
}

// get the spliced mRNA (spliced) sequence
int getMRNASeq(CTIsoform& isoform, const char* contig, char* mRNABuf)
{
    int mRNALength = 0;
    int contigLength = strlen(contig);
    char exonBuf[MAX_MRNA_SIZE];
    for (unsigned int i = 0; i < isoform.exons.size(); i++) {
        int exonStart = isoform.exons.at(i).first;
        int exonEnd = isoform.exons.at(i).second - 1; // intron start - 1
        int exonLength = exonEnd - exonStart + 1;
        // should consider index shift
        if ( exonStart >= 0 && exonEnd <= contigLength && exonLength < MAX_MRNA_SIZE) {
            strncpy(exonBuf, &contig[exonStart], exonLength);
            if (mRNALength + exonLength >= MAX_MRNA_SIZE) {
                return(false); //avoid the buffer overflow
            }
            exonBuf[exonLength] = '\0';

            if (!isoform.forward) {
                reverseComplementKmer(exonBuf);
            } else { // Chek the donor and acceptor site in the intron is GU-AG
                ofstream ofile("doner_acceptor.txt", ios::app);
                const int flankLength = 5;
                const int regLength = flankLength * 2;
                char strand = isoform.forward ? '+' : '-';
                if (i < isoform.exons.size() - 1) {
                    char donor[regLength + 1];
                    strncpy(donor, &contig[exonEnd - flankLength + 1], regLength);
                    for (int j = flankLength; j < regLength ; j++) // show intron in lower case
                        donor[j] = tolower(donor[j]);
                    donor [regLength] = '\0';
                    ofile << "\nDonor " << exonEnd - flankLength + 1 << strand << donor << ';';
                    // cout << "Exon end:"; cout << &(exonBuf[exonLength - 5]) << endl;
                }
                if (i > 0) {
                    char acceptor[regLength + 1];
                    strncpy(acceptor, &contig[exonStart - flankLength], regLength);
                    for (int j = 0; j < flankLength ; j++) // show intron in lower case
                        acceptor[j] = tolower(acceptor[j]);
                    acceptor[regLength] = '\0';
                    ofile << "Acceptor " << exonStart - flankLength << strand << acceptor << ';';
                    // cout << "Exon start:"; for(int j = 0; j < flankLength; j++) { cout << exonBuf[j]; }
                }
            }
            sprintf(&(mRNABuf[mRNALength]), "%s", exonBuf);
            mRNALength += exonLength;
        }
    }
    return(mRNALength);
}